package zpp_nape.shape;
import zpp_nape.Config;
import zpp_nape.Const;
import zpp_nape.util.Flags;
import DummyNapeMain;
import zpp_nape.util.Math;
import zpp_nape.util.Names;
import zpp_nape.util.Pool;
import zpp_nape.util.Lists;
import zpp_nape.shape.Edge;
import zpp_nape.space.Space;
import zpp_nape.shape.Polygon;
import zpp_nape.shape.Shape;
import zpp_nape.phys.FeatureMix;
import zpp_nape.phys.FluidProperties;
import zpp_nape.phys.Material;
import zpp_nape.phys.Body;
import zpp_nape.geom.AABB;
import zpp_nape.geom.Distance;
import zpp_nape.geom.Mat23;
import zpp_nape.geom.Vec2;
import zpp_nape.geom.VecMath;
import zpp_nape.geom.Collide;
import zpp_nape.dynamics.Arbiter;
import zpp_nape.dynamics.Contact;
import zpp_nape.dynamics.InteractionFilter;
import zpp_nape.constraint.Constraint;
import zpp_nape.dynamics.SpaceArbiterList;
import zpp_nape.constraint.Matrices;
import zpp_nape.constraint.PivotJoint;
import zpp_nape.constraint.WeldJoint;
import nape.util.Flags;
import nape.util.Lists;
import nape.util.Debug;
import nape.space.Space;
import nape.shape.Circle;
import nape.shape.Polygon;
import nape.shape.Edge;
import nape.shape.Shape;
import nape.phys.FluidProperties;
import nape.phys.Material;
import nape.phys.Body;
import nape.geom.AABB;
import nape.geom.Geom;
import nape.geom.Mat23;
import nape.geom.Vec2;
import nape.dynamics.Contact;
import nape.dynamics.Arbiter;
import nape.dynamics.InteractionFilter;
#if swc@:keep#end class ZPP_Circle extends ZPP_Shape{
    public var outer_zn:Circle;
    public var radius:Float;
    public var rollingFriction:Bool;
    public function new(){
        super(ZPP_Flags.id_ShapeType_CIRCLE);
        circle=this;
        rollingFriction=true;
        zip_localCOM=false;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function invalidate_radius(){
        invalidate_area_inertia();
        invalidate_angDrag();
        invalidate_aabb();
        if(body!=null)body.wakeall();
    }
    public function setupLocalCOM(){
        var me=this;
        wrap_localCOM=new Vec2(localCOMx,localCOMy);
        wrap_localCOM.zpp_inner.inuse=true;
        wrap_localCOM.zpp_inner._validate=function(){
            me.wrap_localCOM.zpp_inner.x=me.localCOMx;
            me.wrap_localCOM.zpp_inner.y=me.localCOMy;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](me.wrap_localCOM.zpp_inner.x);
                        ret;
                        #else Math.isNaN(me.wrap_localCOM.zpp_inner.x);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(me.wrap_localCOM.zpp_inner.x)"+") :: "+("vec_set(in n: "+"me.wrap_localCOM.zpp_inner."+",in x: "+"me.localCOMx"+",in y: "+"me.localCOMy"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](me.wrap_localCOM.zpp_inner.y);
                        ret;
                        #else Math.isNaN(me.wrap_localCOM.zpp_inner.y);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(me.wrap_localCOM.zpp_inner.y)"+") :: "+("vec_set(in n: "+"me.wrap_localCOM.zpp_inner."+",in x: "+"me.localCOMx"+",in y: "+"me.localCOMy"+")");
                #end
            };
        };
        wrap_localCOM.zpp_inner._invalidate=function(x:ZPP_Vec2){
            {
                me.localCOMx=x.x;
                me.localCOMy=x.y;
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.localCOMx);
                            ret;
                            #else Math.isNaN(me.localCOMx);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.localCOMx)"+") :: "+("vec_set(in n: "+"me.localCOM"+",in x: "+"x.x"+",in y: "+"x.y"+")");
                    #end
                };
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.localCOMy);
                            ret;
                            #else Math.isNaN(me.localCOMy);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.localCOMy)"+") :: "+("vec_set(in n: "+"me.localCOM"+",in x: "+"x.x"+",in y: "+"x.y"+")");
                    #end
                };
            };
            me.invalidate_localCOM();
            if(me.body!=null)me.body.wakeall();
        };
        wrap_localCOM.zpp_inner._immutable=function(){
            if(me.body!=null&&me.body.isStatic()&&me.body.space!=null)throw "Error: Cannot modify localCOM of Circle added to a static Body whilst within a Space";
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function __validate_aabb(){
        validate_worldCOM();
        var rx:Float=radius;
        var ry:Float=radius;
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](rx);
                    ret;
                    #else Math.isNaN(rx);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(rx)"+") :: "+("vec_new(in n: "+"r"+",in x: "+"radius"+",in y: "+"radius"+")");
            #end
        };
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](ry);
                    ret;
                    #else Math.isNaN(ry);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(ry)"+") :: "+("vec_new(in n: "+"r"+",in x: "+"radius"+",in y: "+"radius"+")");
            #end
        };
        {
            aabb.minx=worldCOMx-rx;
            aabb.miny=worldCOMy-ry;
        };
        {
            aabb.maxx=worldCOMx+rx;
            aabb.maxy=worldCOMy+ry;
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function __validate_area_inertia(){
        var r2=radius*radius;
        area=r2*Math.PI;
        inertia=r2*0.5+(localCOMx*localCOMx+localCOMy*localCOMy);
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function __validate_angDrag(){
        var lc=(localCOMx*localCOMx+localCOMy*localCOMy);
        var r2=radius*radius;
        var skin=material.dynamicFriction*ZPP_Config.ANGDRAGCOEF_FRICTION;
        angDrag=(lc+2*r2)*skin+0.5*ZPP_Config.ANGDRAGCOEF_DRAG*(1+ZPP_Config.ANGDRAGCOEF_VACUUM)*lc;
        angDrag/=(2*(lc+0.5*r2));
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function __scale(sx:Float,sy:Float){
        var factor=((sx<0?-sx:sx)+(sy<0?-sy:sy))/2;
        radius*=factor<0?-factor:factor;
        invalidate_radius();
        if((localCOMx*localCOMx+localCOMy*localCOMy)>0){
            localCOMx*=sx;
            localCOMy*=sy;
            invalidate_localCOM();
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function __translate(x:Float,y:Float){
        {
            var t=(1.0);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"localCOM"+",in b: "+""+",in s: "+"1.0"+")");
                #end
            };
            localCOMx+=x*t;
            localCOMy+=y*t;
        };
        invalidate_localCOM();
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function __rotate(x:Float,y:Float){
        if((localCOMx*localCOMx+localCOMy*localCOMy)>0){
            var tx:Float;
            var ty:Float;
            {
                tx=(y*localCOMx-x*localCOMy);
                ty=(localCOMx*x+localCOMy*y);
            };
            {
                localCOMx=tx;
                localCOMy=ty;
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](localCOMx);
                            ret;
                            #else Math.isNaN(localCOMx);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(localCOMx)"+") :: "+("vec_set(in n: "+"localCOM"+",in x: "+"tx"+",in y: "+"ty"+")");
                    #end
                };
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](localCOMy);
                            ret;
                            #else Math.isNaN(localCOMy);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(localCOMy)"+") :: "+("vec_set(in n: "+"localCOM"+",in x: "+"tx"+",in y: "+"ty"+")");
                    #end
                };
            };
            invalidate_localCOM();
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function __transform(m:Mat23){
        var det=(m.a*m.d-m.b*m.c);
        if(det<0)det=-det;
        radius*=Math.sqrt(det);
        {
            var t=m.a*localCOMx+m.b*localCOMy;
            localCOMy=m.c*localCOMx+m.d*localCOMy;
            localCOMx=t;
        };
        {
            var t=(1.0);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"localCOM"+",in b: "+"m.t"+",in s: "+"1.0"+")");
                #end
            };
            localCOMx+=m.tx*t;
            localCOMy+=m.ty*t;
        };
        invalidate_radius();
        invalidate_localCOM();
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function __copy(){
        var ret=new Circle(radius).zpp_inner_zn;
        {
            ret.localCOMx=localCOMx;
            ret.localCOMy=localCOMy;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ret.localCOMx);
                        ret;
                        #else Math.isNaN(ret.localCOMx);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ret.localCOMx)"+") :: "+("vec_set(in n: "+"ret.localCOM"+",in x: "+"localCOMx"+",in y: "+"localCOMy"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ret.localCOMy);
                        ret;
                        #else Math.isNaN(ret.localCOMy);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ret.localCOMy)"+") :: "+("vec_set(in n: "+"ret.localCOM"+",in x: "+"localCOMx"+",in y: "+"localCOMy"+")");
                #end
            };
        };
        ret.zip_localCOM=false;
        ret.rollingFriction=rollingFriction;
        return ret;
    }
}
